use anyhow::Result;
use iroh_app;
use serde::{Deserialize, Serialize};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::{sync::Mutex, task};

#[derive(Clone)]
pub struct IrohNodeWrapper {
    is_running: Arc<AtomicBool>,
    handle: Arc<Mutex<Option<task::JoinHandle<()>>>>,
}

impl Default for IrohNodeWrapper {
    fn default() -> Self {
        Self {
            is_running: Arc::new(AtomicBool::new(false)),
            handle: Arc::new(Mutex::new(None)),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct IrohInfo {
    pub node_id: Option<String>,
    pub topic: Option<String>,
    pub ticket: Option<String>,
}

impl IrohNodeWrapper {
    pub async fn open_node(&self) -> Result<(), String> {
        let topic = None;
        let secret_key = None;
        let relay = None;
        let no_relay = false;
        let name = None;
        let bind_port = 0;

        // 在后台任务中运行 iroh
        let is_running_clone = self.is_running.clone();
        let handle_clone = self.handle.clone();

        // 立即设置运行状态为 true，因为我们正在启动
        is_running_clone.store(true, Ordering::SeqCst);
        println!("Iroh node status set to running");

        // 在后台任务中运行 iroh
        let handle = task::spawn(async move {
            println!("DEBUG: Starting iroh in spawn task");
            let result = iroh_app::open(topic, secret_key, relay, no_relay, name, bind_port).await;

            match result {
                Ok((topic_id, node_id, _ticket)) => {
                    println!(
                        "Node info received: node_id={}, topic={}, ticket=...",
                        node_id, topic_id
                    );
                }
                Err(e) => {
                    eprintln!("Iroh node error: {:?}", e);
                }
            }

            // 如果 iroh 退出，重置状态
            is_running_clone.store(false, Ordering::SeqCst);
            println!("Iroh node exited, status updated to stopped");
        });

        // 保存任务句柄
        *handle_clone.lock().await = Some(handle);

        Ok(())
    }

    pub async fn join_node(&self, ticket: String) -> Result<(), String> {
        let secret_key = None;
        let relay = None;
        let no_relay = false;
        let name = None;
        let bind_port = 0;

        // 在后台任务中运行 iroh
        let is_running_clone = self.is_running.clone();
        let handle_clone = self.handle.clone();

        // 立即设置运行状态为 true，因为我们正在启动
        is_running_clone.store(true, Ordering::SeqCst);
        println!("Iroh node status set to running");

        // 在后台任务中运行 iroh
        let handle = task::spawn(async move {
            println!("DEBUG: Starting iroh join in spawn task");
            let result = iroh_app::join(ticket, secret_key, relay, no_relay, name, bind_port).await;

            // 如果 iroh 退出，重置状态
            is_running_clone.store(false, Ordering::SeqCst);
            println!("Iroh node exited, status updated to stopped");

            if let Err(e) = result {
                eprintln!("Iroh node error: {:?}", e);
            }
        });

        // 保存任务句柄
        *handle_clone.lock().await = Some(handle);

        Ok(())
    }

    pub async fn close_node(&self) {
        // 先关闭 iroh 节点
        iroh_app::close().await;

        // 等待后台任务完成
        let mut handle = self.handle.lock().await;
        if let Some(handle) = handle.take() {
            // 等待任务完成，但设置一个超时时间以避免无限等待
            match tokio::time::timeout(std::time::Duration::from_secs(5), handle).await {
                Ok(Ok(())) => {
                    println!("Iroh background task completed successfully");
                }
                Ok(Err(e)) => {
                    eprintln!("Iroh background task failed: {:?}", e);
                }
                Err(_) => {
                    eprintln!("Iroh background task did not complete within timeout");
                }
            }
        }

        // 重置运行状态
        self.is_running.store(false, Ordering::SeqCst);
        println!("Iroh node status updated to stopped");
    }

    pub fn is_node_running(&self) -> bool {
        self.is_running.load(Ordering::SeqCst)
    }

    pub async fn get_node_info(&self) -> Result<IrohInfo, String> {
        if !self.is_node_running() {
            return Ok(IrohInfo {
                node_id: None,
                topic: None,
                ticket: None,
            });
        }

        // 调用 iroh-app::get_node_info
        println!("DEBUG: Calling iroh_app::get_node_info()");
        match iroh_app::get_node_info().await {
            Ok(info) => {
                println!("DEBUG: Got node info: {:?}", info);
                Ok(IrohInfo {
                    node_id: info.node_id,
                    topic: info.topic,
                    ticket: info.ticket,
                })
            }
            Err(e) => {
                eprintln!("Error getting node info: {:?}", e);
                Ok(IrohInfo {
                    node_id: None,
                    topic: None,
                    ticket: None,
                })
            }
        }
    }
}
